#include <unistd.h>
#include <pthread.h>
#include <string>
#include "RingQueue.hpp"
using namespace RingQueueModule;
int data = 1;

// class ThreadData
// {
// public:
//     ThreadData(const std::string &name)
//     :_name(name)
//     {}
//     ~ThreadData(){}
//     ringqueue<int>* _rq;
//     std::string _name;
// };

class ThreadData
{
public:
    ringqueue<int>* _rq;
    std::string _name;
};

void *Produce(void *args)
{
    ThreadData* tdp = static_cast<ThreadData*>(args);
    while(true)
    {
        /* 生产任务 */
        sleep(1); /* 模拟生产任务过程的耗时 */
        std::cout << tdp->_name << " 生产了一个任务: " << data << std::endl;
        tdp->_rq->Put(data);
        data++;
    }
}

void *Consumer(void *args)
{
    ThreadData* tdc = static_cast<ThreadData*>(args);
    while(true)
    {
        /* 消费任务 */
        int out = 0;
        tdc->_rq->Get(&out);
        std::cout << tdc->_name << " 消费了一个任务: " << out << std::endl;
    }
}


int main()
{
    // 扩展认识: 阻塞队列: 可以放任务吗？
    // 申请阻塞队列
    ringqueue<int> *rq = new ringqueue<int>();

    // 构建生产和消费者
    // 如果我们改成多生产多消费呢？？
    // 单单: cc, pp -> 互斥关系不需要维护，互斥与同步
    // 多多：cc, pp -> 之间的互斥关系！ 访问资源加锁！
    pthread_t c[2], p[3];

    ThreadData *td = new ThreadData();
    td->_name = "cthread-1";
    td->_rq = rq;
    pthread_create(c, nullptr, Consumer, td);

    ThreadData *td2 = new ThreadData();
    td2->_name = "cthread-2";
    td2->_rq = rq;
    pthread_create(c + 1, nullptr, Consumer, td2);

    ThreadData *td3 = new ThreadData();
    td3->_name = "pthread-3";
    td3->_rq = rq;
    pthread_create(p, nullptr, Produce, td3);

    ThreadData *td4 = new ThreadData();
    td4->_name = "pthread-4";
    td4->_rq = rq;
    pthread_create(p + 1, nullptr, Produce, td4);

    ThreadData *td5 = new ThreadData();
    td5->_name = "pthread-5";
    td5->_rq = rq;
    pthread_create(p + 2, nullptr, Produce, td5);

    pthread_join(c[0], nullptr);
    pthread_join(c[1], nullptr);
    pthread_join(p[0], nullptr);
    pthread_join(p[1], nullptr);
    pthread_join(p[2], nullptr);

    #if 0
    /* 单单 */
    pthread_t p[1], c[1];

    /* 循环队列 */
    ringqueue<int>* rq = new ringqueue<int>();

    ThreadData* tdp = new ThreadData("Thread-p");
    tdp->_rq = rq;

    ThreadData* tdc = new ThreadData("Thread-c");
    tdc->_rq = rq;

    pthread_create(&p[0], nullptr, Produce, (void*)tdp);
    pthread_create(&c[0], nullptr, Consumer, (void*)tdc);


    pthread_join(p[0], nullptr);
    pthread_join(c[0], nullptr);
    

    delete rq;
    delete tdp;
    delete tdc;
    #endif
    return 0;
}